package com.ttn.student.service.impl;

import cn.hutool.core.util.NumberUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.ttn.common.core.entity.Result;
import com.ttn.common.core.entity.business.CourseUnitOralPractice;
import com.ttn.common.core.entity.studentrecord.*;
import com.ttn.common.core.entity.studentrecord.query.QueryStudyLeaderboardQuery;
import com.ttn.common.core.entity.studentrecord.query.TestStudyRecordQuery;
import com.ttn.common.core.entity.studentrecord.vo.LikeRecordVO;
import com.ttn.common.core.entity.studentrecord.vo.SaveOralPracticeStudyRecordDetailsVO;
import com.ttn.common.core.entity.studentrecord.vo.TestStudyRecordDetailsVO;
import com.ttn.student.mapper.OralPracticeStudyRecordDetailsMapper;
import com.ttn.student.service.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
public class OralPracticeStudyRecordDetailsServiceImpl extends ServiceImpl<OralPracticeStudyRecordDetailsMapper, OralPracticeStudyRecordDetails> implements OralPracticeStudyRecordDetailsService {
    @Resource
    private OralPracticeStudyRecordDetailsMapper oralPracticeStudyRecordDetailsMapper;
    @Resource
    private TestStudyRecordService testStudyRecordService;
    @Resource
    private LikeRecordService likeRecordService;
    @Resource
    private LearningProgressRecordService learningProgressRecordService;
    @Resource
    private StudentRecordService studentRecordService;


    @Override
    public List<CourseUnitOralPractice> getUnfinishedCourseUnitOralPracticeList(TestStudyRecord testStudyRecord) {
        return oralPracticeStudyRecordDetailsMapper.getUnfinishedCourseUnitOralPracticeList(testStudyRecord);
    }

    @Override
    @Transactional
    public Result saveOralPracticeStudyRecordDetails(OralPracticeStudyRecordDetails oralPracticeStudyRecordDetails) {
        TestStudyRecordDetailsVO testStudyRecordDetailsVO = new TestStudyRecordDetailsVO();

        this.save(oralPracticeStudyRecordDetails);
        TestStudyRecord testStudyRecord = testStudyRecordService.getById(oralPracticeStudyRecordDetails.getStudyRecordId());
        LambdaQueryWrapper<OralPracticeStudyRecordDetails> oralPracticeStudyRecordDetailsLambdaQueryWrapper = new LambdaQueryWrapper<>();
        oralPracticeStudyRecordDetailsLambdaQueryWrapper.eq(OralPracticeStudyRecordDetails::getStudyRecordId, oralPracticeStudyRecordDetails.getStudyRecordId());

        //保存答题数量
        Integer studyNum = Math.toIntExact(this.count(oralPracticeStudyRecordDetailsLambdaQueryWrapper));
        testStudyRecord.setStudyNum(studyNum);
        testStudyRecordService.updateById(testStudyRecord);
        if (studyNum.equals(testStudyRecord.getCourseUnitNum())) {
            //获取答对题目数
            LambdaQueryWrapper<OralPracticeStudyRecordDetails> oralPracticeStudyRecordDetailsLambdaQueryWrapper1 = new LambdaQueryWrapper<>();
            oralPracticeStudyRecordDetailsLambdaQueryWrapper1.ge(OralPracticeStudyRecordDetails::getScore, 60);
            oralPracticeStudyRecordDetailsLambdaQueryWrapper1.eq(OralPracticeStudyRecordDetails::getStudyRecordId, oralPracticeStudyRecordDetails.getStudyRecordId());
            Long correctAnswer = this.count(oralPracticeStudyRecordDetailsLambdaQueryWrapper1);
            testStudyRecord.setCorrectAmount(Math.toIntExact(correctAnswer));
            //获取所有答题用户数量
            QueryWrapper<TestStudyRecord> testStudyRecordLambdaQueryWrapper = new QueryWrapper<>();
            testStudyRecordLambdaQueryWrapper.select("DISTINCT student_id  ")
                    .lambda()
                    .eq(TestStudyRecord::getCourseUnitId, oralPracticeStudyRecordDetails.getCourseUnitId())
                    .eq(TestStudyRecord::getFinishFlag, 1)
                    .eq(TestStudyRecord::getUnitTaskType, "4")
                    .ne(TestStudyRecord::getStudentId, testStudyRecord.getStudentId());
            long countAll = testStudyRecordService.count(testStudyRecordLambdaQueryWrapper);
            testStudyRecordDetailsVO.setCompleted(Math.toIntExact(countAll));
            long beyondProportionNum = 0;
            if (countAll != 0) {
                //获取超过的用户
                testStudyRecordLambdaQueryWrapper.lambda().gt(TestStudyRecord::getScore, testStudyRecord.getScore());
                beyondProportionNum = testStudyRecordService.count(testStudyRecordLambdaQueryWrapper);
                //更新得分和排名
                testStudyRecord.setBeyondProportion(BigDecimal.valueOf(NumberUtil.mul(NumberUtil.sub(1, NumberUtil.div(beyondProportionNum, countAll, 2)), 100)));
            } else {
                testStudyRecord.setBeyondProportion(BigDecimal.valueOf(100));
            }

            testStudyRecordDetailsVO.setTestStudyRecord(testStudyRecord);
            LambdaQueryWrapper<OralPracticeStudyRecordDetails> oralPracticeStudyRecordDetailsLambdaQueryWrapperScore = new LambdaQueryWrapper<>();
            oralPracticeStudyRecordDetailsLambdaQueryWrapperScore.eq(OralPracticeStudyRecordDetails::getStudyRecordId, testStudyRecord.getId());
            testStudyRecord.setScore(Double.valueOf(this.list(oralPracticeStudyRecordDetailsLambdaQueryWrapperScore).stream().mapToInt(OralPracticeStudyRecordDetails::getScore).average().getAsDouble()).intValue());
            testStudyRecord.setFinishFlag(1);
            testStudyRecordService.updateById(testStudyRecord);
            //查询前20名
            List<SaveOralPracticeStudyRecordDetailsVO> saveOralPracticeStudyRecordDetailsVOList = oralPracticeStudyRecordDetailsMapper.getTop20(testStudyRecord);
            if (saveOralPracticeStudyRecordDetailsVOList.size() > 0) {
                LambdaQueryWrapper<OralPracticeStudyRecordDetails> oralPracticeStudyRecordDetailsLambdaQueryWrapper2 = new LambdaQueryWrapper<>();
                oralPracticeStudyRecordDetailsLambdaQueryWrapper2.in(OralPracticeStudyRecordDetails::getStudyRecordId, saveOralPracticeStudyRecordDetailsVOList.stream().map(SaveOralPracticeStudyRecordDetailsVO::getId).collect(Collectors.toList()));
                //获取前20名音频文件
                List<OralPracticeStudyRecordDetails> oralPracticeStudyRecordDetailsList = this.list(oralPracticeStudyRecordDetailsLambdaQueryWrapper2);
                if (oralPracticeStudyRecordDetailsList.size() > 0) {
                    List<String> spokenAudioFile = Lists.newArrayList();
                    Map<Integer, List<OralPracticeStudyRecordDetails>> oralPracticeStudyRecordDetailsListMap = oralPracticeStudyRecordDetailsList.stream().collect(Collectors.groupingBy(OralPracticeStudyRecordDetails::getStudyRecordId));
                    saveOralPracticeStudyRecordDetailsVOList.stream().forEach(saveOralPracticeStudyRecordDetailsVO -> {
                        oralPracticeStudyRecordDetailsListMap.get(saveOralPracticeStudyRecordDetailsVO.getId()).forEach(oralConversationStudyRecordDetails -> {
                            spokenAudioFile.add(oralConversationStudyRecordDetails.getUserAnswer());
                        });
                        saveOralPracticeStudyRecordDetailsVO.setSpokenAudioFile(spokenAudioFile);
                    });
                }
                //获取点赞总数
                List<LikeRecordVO> likeRecordVOList = likeRecordService.getLikeCount(saveOralPracticeStudyRecordDetailsVOList.stream().map(SaveOralPracticeStudyRecordDetailsVO::getId).collect(Collectors.toList()));
                if (likeRecordVOList.size() > 0) {
                    saveOralPracticeStudyRecordDetailsVOList.stream().forEach(saveOralPracticeStudyRecordDetailsVO -> {
                        LikeRecordVO likeRecordVO = likeRecordVOList.stream().filter(likeRecord -> likeRecord.getStudyRecordId().equals(saveOralPracticeStudyRecordDetailsVO.getId())).findFirst().orElse(null);
                        if (Objects.nonNull(likeRecordVO)) {
                            saveOralPracticeStudyRecordDetailsVO.setLikeNum(likeRecordVO.getLikeNum());
                        } else {
                            saveOralPracticeStudyRecordDetailsVO.setLikeNum(0);
                        }
                    });
                }
            }
            LambdaQueryWrapper<OralPracticeStudyRecordDetails> oralPracticeStudyRecordDetailsLambdaQueryWrapper2 = new LambdaQueryWrapper<>();
            oralPracticeStudyRecordDetailsLambdaQueryWrapper2.eq(OralPracticeStudyRecordDetails::getStudyRecordId, testStudyRecord.getId());
            List<OralPracticeStudyRecordDetails> userOralPracticeStudyRecordDetailsList = this.list(oralPracticeStudyRecordDetailsLambdaQueryWrapper2);
            if (userOralPracticeStudyRecordDetailsList.size() > 0) {
                List<String> spokenAudioFile = Lists.newArrayList();
                userOralPracticeStudyRecordDetailsList.forEach(oralConversationStudyRecordDetails -> {
                    spokenAudioFile.add(oralConversationStudyRecordDetails.getUserAnswer());
                });
                testStudyRecordDetailsVO.setSpokenAudioFile(spokenAudioFile);
            }
            testStudyRecordDetailsVO.setLikeNum(0);
            testStudyRecordDetailsVO.setOralPracticeStudyRecordDetails(saveOralPracticeStudyRecordDetailsVOList);
            testStudyRecordDetailsVO.setRanking(Math.toIntExact(beyondProportionNum + 1));
            StudentRecord studentRecord = studentRecordService.getById(testStudyRecord.getStudentId());
            if (Objects.nonNull(studentRecord)) {
                testStudyRecordDetailsVO.setAvatarUrl(studentRecord.getAvatarUrl());
            }
            LambdaQueryWrapper<LearningProgressRecord> learningProgressRecordLambdaQueryWrapper = new LambdaQueryWrapper<>();
            learningProgressRecordLambdaQueryWrapper.eq(LearningProgressRecord::getStudentId, testStudyRecord.getStudentId());
            learningProgressRecordLambdaQueryWrapper.eq(LearningProgressRecord::getCourseUnitId, testStudyRecord.getCourseUnitId());
            LearningProgressRecord learningProgressRecord = learningProgressRecordService.getOne(learningProgressRecordLambdaQueryWrapper);
            learningProgressRecord.setCorrectAmount(testStudyRecordService.queryTotalCorrectAmountByUnitIdId(testStudyRecord.getCourseUnitId(), testStudyRecord.getStudentId()));

            int studyNumByGrade = testStudyRecordService.queryTotalTestStudyRecordByUnitIdId(testStudyRecord.getCourseUnitId(),
                    testStudyRecord.getStudentId());

            learningProgressRecord.setStudyNum(studyNumByGrade);
            if (learningProgressRecord.getGrade() > 5 && testStudyRecord.getScore() >= 60) {
                learningProgressRecord.setFinishFlag(1);
                //调用升级方法
                learningProgressRecordService.queryJudgeGrade(testStudyRecord.getStudentId());
            }
            learningProgressRecordService.updateById(learningProgressRecord);
            return Result.success(testStudyRecordDetailsVO);
        }
        return Result.success();
    }

    @Override
    public Result queryOralPracticeStudyLeaderboard(QueryStudyLeaderboardQuery queryStudyLeaderboardQuery) {
        TestStudyRecordDetailsVO testStudyRecordDetailsVO = new TestStudyRecordDetailsVO();
        LambdaQueryWrapper<TestStudyRecord> testStudyRecordLambdaQueryWrapper = new LambdaQueryWrapper<>();
        testStudyRecordLambdaQueryWrapper.eq(TestStudyRecord::getFinishFlag, 1);
        testStudyRecordLambdaQueryWrapper.eq(TestStudyRecord::getCourseUnitId, queryStudyLeaderboardQuery.getCourseUnitId());
        testStudyRecordLambdaQueryWrapper.eq(TestStudyRecord::getStudentId, queryStudyLeaderboardQuery.getStudentId());
        testStudyRecordLambdaQueryWrapper.eq(TestStudyRecord::getUnitTaskType, "4");
        testStudyRecordLambdaQueryWrapper.last(" limit 1");
        testStudyRecordLambdaQueryWrapper.orderByDesc(TestStudyRecord::getScore);
        TestStudyRecord testStudyRecord = testStudyRecordService.getOne(testStudyRecordLambdaQueryWrapper);
        if (Objects.nonNull(testStudyRecord)) {
            testStudyRecordDetailsVO.setTestStudyRecord(testStudyRecord);
            StudentRecord studentRecord = studentRecordService.getById(testStudyRecord.getStudentId());
            if (Objects.nonNull(studentRecord)) {
                testStudyRecordDetailsVO.setAvatarUrl(studentRecord.getAvatarUrl());
            }

            //查询前20名
            List<SaveOralPracticeStudyRecordDetailsVO> saveOralPracticeStudyRecordDetailsVOList = oralPracticeStudyRecordDetailsMapper.getTop20(testStudyRecord);
            if (saveOralPracticeStudyRecordDetailsVOList.size() > 0 && Objects.nonNull(saveOralPracticeStudyRecordDetailsVOList.get(0).getId())) {
                LambdaQueryWrapper<OralPracticeStudyRecordDetails> oralPracticeStudyRecordDetailsLambdaQueryWrapper2 = new LambdaQueryWrapper<>();
                oralPracticeStudyRecordDetailsLambdaQueryWrapper2.in(OralPracticeStudyRecordDetails::getStudyRecordId, saveOralPracticeStudyRecordDetailsVOList.stream().map(SaveOralPracticeStudyRecordDetailsVO::getId).collect(Collectors.toList()));
                //获取前20名音频文件
                List<OralPracticeStudyRecordDetails> oralPracticeStudyRecordDetailsList = this.list(oralPracticeStudyRecordDetailsLambdaQueryWrapper2);
                if (oralPracticeStudyRecordDetailsList.size() > 0) {
                    List<String> spokenAudioFile = Lists.newArrayList();
                    Map<Integer, List<OralPracticeStudyRecordDetails>> oralPracticeStudyRecordDetailsListMap = oralPracticeStudyRecordDetailsList.stream().collect(Collectors.groupingBy(OralPracticeStudyRecordDetails::getStudyRecordId));
                    saveOralPracticeStudyRecordDetailsVOList.stream().forEach(saveOralPracticeStudyRecordDetailsVO -> {
                        oralPracticeStudyRecordDetailsListMap.get(saveOralPracticeStudyRecordDetailsVO.getId()).forEach(oralConversationStudyRecordDetails -> {
                            spokenAudioFile.add(oralConversationStudyRecordDetails.getUserAnswer());
                        });
                        saveOralPracticeStudyRecordDetailsVO.setSpokenAudioFile(spokenAudioFile);
                    });
                }
                //获取点赞总数
                List<LikeRecordVO> likeRecordVOList = likeRecordService.getLikeCount(saveOralPracticeStudyRecordDetailsVOList.stream().map(SaveOralPracticeStudyRecordDetailsVO::getId).collect(Collectors.toList()));
                if (likeRecordVOList.size() > 0) {
                    saveOralPracticeStudyRecordDetailsVOList.stream().forEach(saveOralPracticeStudyRecordDetailsVO -> {
                        LikeRecordVO likeRecordVO = likeRecordVOList.stream().filter(likeRecord -> likeRecord.getStudyRecordId().equals(saveOralPracticeStudyRecordDetailsVO.getId())).findFirst().orElse(null);
                        if (Objects.nonNull(likeRecordVO)) {
                            saveOralPracticeStudyRecordDetailsVO.setLikeNum(likeRecordVO.getLikeNum());
                        } else {
                            saveOralPracticeStudyRecordDetailsVO.setLikeNum(0);
                        }
                    });
                }
                testStudyRecordDetailsVO.setOralPracticeStudyRecordDetails(saveOralPracticeStudyRecordDetailsVOList);
            }
            LambdaQueryWrapper<OralPracticeStudyRecordDetails> oralPracticeStudyRecordDetailsLambdaQueryWrapper2 = new LambdaQueryWrapper<>();
            oralPracticeStudyRecordDetailsLambdaQueryWrapper2.eq(OralPracticeStudyRecordDetails::getStudyRecordId, testStudyRecord.getId());
            List<OralPracticeStudyRecordDetails> userOralPracticeStudyRecordDetailsList = this.list(oralPracticeStudyRecordDetailsLambdaQueryWrapper2);
            if (userOralPracticeStudyRecordDetailsList.size() > 0) {
                List<String> spokenAudioFile = Lists.newArrayList();
                userOralPracticeStudyRecordDetailsList.forEach(oralConversationStudyRecordDetails -> {
                    spokenAudioFile.add(oralConversationStudyRecordDetails.getUserAnswer());
                });
                testStudyRecordDetailsVO.setSpokenAudioFile(spokenAudioFile);
            }
            testStudyRecordDetailsVO.setLikeNum(0);
            QueryWrapper<TestStudyRecord> studyRecordLambdaQueryWrapperCount = new QueryWrapper<>();
            studyRecordLambdaQueryWrapperCount.select(" DISTINCT student_id  ")
                    .lambda()
                    .eq(TestStudyRecord::getCourseUnitId, queryStudyLeaderboardQuery.getCourseUnitId())
                    .eq(TestStudyRecord::getFinishFlag, 1)
                    .eq(TestStudyRecord::getUnitTaskType, "4")
                    .ne(TestStudyRecord::getStudentId, queryStudyLeaderboardQuery.getStudentId());
            //获取所有答题用户数量
            testStudyRecordDetailsVO.setCompleted(Math.toIntExact(testStudyRecordService.count(studyRecordLambdaQueryWrapperCount) + 1));
            LambdaQueryWrapper<TestStudyRecord> studyRecordLambdaQueryWrapper = new LambdaQueryWrapper<>();
            studyRecordLambdaQueryWrapper.eq(TestStudyRecord::getCourseUnitId, testStudyRecord.getCourseUnitId());
            studyRecordLambdaQueryWrapper.eq(TestStudyRecord::getFinishFlag, 1);
            studyRecordLambdaQueryWrapper.eq(TestStudyRecord::getUnitTaskType, "4");
            studyRecordLambdaQueryWrapper.gt(TestStudyRecord::getScore, testStudyRecord.getScore());
            testStudyRecordDetailsVO.setRanking(Math.toIntExact(testStudyRecordService.count(studyRecordLambdaQueryWrapper) + 1));
            LambdaQueryWrapper<LikeRecord> likeRecordLambdaQueryWrapper = new LambdaQueryWrapper<>();
            likeRecordLambdaQueryWrapper.eq(LikeRecord::getStudyRecordId, testStudyRecord.getId());
            testStudyRecordDetailsVO.setLikeNum(Math.toIntExact(likeRecordService.count(likeRecordLambdaQueryWrapper)));

        }
        return Result.success(testStudyRecordDetailsVO);
    }

    @Override
    public Result queryOralPracticeStudyRecordDetails(TestStudyRecordQuery testStudyRecordQuery) {
        //获取分数最高的一次测试记录
        TestStudyRecordDetailsVO testStudyRecordDetailsVO = new TestStudyRecordDetailsVO();
        LambdaQueryWrapper<TestStudyRecord> testStudyRecordLambdaQueryWrapper = new LambdaQueryWrapper<>();
        testStudyRecordLambdaQueryWrapper.eq(TestStudyRecord::getStudentId, testStudyRecordQuery.getStudentId());
        testStudyRecordLambdaQueryWrapper.eq(TestStudyRecord::getCourseUnitId, testStudyRecordQuery.getCourseUnitId());
        testStudyRecordLambdaQueryWrapper.eq(TestStudyRecord::getUnitTaskType, "4");
        testStudyRecordLambdaQueryWrapper.eq(TestStudyRecord::getFinishFlag, 1);
        testStudyRecordLambdaQueryWrapper.orderByDesc(TestStudyRecord::getScore);
        testStudyRecordLambdaQueryWrapper.last(" limit 1");
        TestStudyRecord testStudyRecord = testStudyRecordService.getOne(testStudyRecordLambdaQueryWrapper);
        if (Objects.nonNull(testStudyRecord)) {
            testStudyRecordDetailsVO.setTestStudyRecord(testStudyRecord);
            LambdaQueryWrapper<OralPracticeStudyRecordDetails> oralPracticeStudyRecordDetailsLambdaQueryWrapper = new LambdaQueryWrapper<>();
            oralPracticeStudyRecordDetailsLambdaQueryWrapper.eq(OralPracticeStudyRecordDetails::getStudyRecordId, testStudyRecord.getId());
            List<OralPracticeStudyRecordDetails> oralPracticeStudyRecordDetailList = this.list(oralPracticeStudyRecordDetailsLambdaQueryWrapper);
            if (oralPracticeStudyRecordDetailList.size() > 0) {
                List<String> spokenAudioFile = Lists.newArrayList();
                oralPracticeStudyRecordDetailList.forEach(oralConversationStudyRecordDetails -> {
                    spokenAudioFile.add(oralConversationStudyRecordDetails.getUserAnswer());
                });
                testStudyRecordDetailsVO.setSpokenAudioFile(spokenAudioFile);
            }
        }
        return Result.success(testStudyRecordDetailsVO);
    }
}
